#!/usr/bin/env python
#==============================================================================
#
#  $Id$
#
"""
    Unit tests for blists.
"""
#
#  Copyright (C) 2007 Michael A. Muller
#
#   This file is part of ODB.
#
#   ODB is free software: you can redistribute it and/or modify it under the 
#   terms of the GNU Lesser General Public License as published by the Free 
#   Software Foundation, either version 3 of the License, or (at your option) 
#   any later version.
#
#   ODB is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU Lesser General Public License for more details.
#
#   You should have received a copy of the GNU Lesser General Public License 
#   along with ODB.  If not, see <http://www.gnu.org/licenses/>.
#
#==============================================================================

import unittest, random, shutil, os, sys
import fixpath
#from odb.mem import MemEnv
from odb.full import FullEnv

# 1 = give basic info
# 2 = give massive detail
verbosity = 0

class test_blist(unittest.TestCase):

    def checkContents(self):
        cur = self.blist.cursor()
        i = 0
        for item in self.blist.cursor():
            if verbosity > 1: print 'got %s, want %s' % (item, self.items[i])
            self.assertEquals(self.items[i], item)
            i += 1

        self.assertEquals(i, len(self.items))

    def setUp(self):
        if os.path.exists('odb_test_db'):
            shutil.rmtree('odb_test_db')
        self.items = []
        self.loadDB()
    
    def loadDB(self):
        self.env = FullEnv('odb_test_db') #MemEnv('odb_test_db')
        self.blist = self.env.getBListDB('blist')

    def tearDown(self):
        shutil.rmtree('odb_test_db')

    def testBasic(self):
        self.items.append(100)
        self.blist.append(100)
        self.assertEquals(self.blist[0], 100)
        self.checkContents()
    
    def testLenIsInt(self):
        self.blist.append(100)
        self.blist.append(200)
        self.env.checkpoint()
        self.loadDB()
        self.assert_(isinstance(len(self.blist), int))
    
    def testLoad(self):
        self.env.checkpoint()
        self.blist.append(100)
        self.loadDB()

    def testPop(self):
        for i in range(7):
            self.blist.append(i)
        
        self.assertEquals(self.blist.pop(), 6)
        self.assertEquals(self.blist.pop(0), 0)
        self.assertEquals(self.blist.pop(2), 3)
        self.assertRaises(IndexError, self.blist.pop, 10)
    def testRandomly(self):
        if not verbosity: print 'test of 1000 actions: %03d' % 0,
        random.seed('spug r0kz!')
        
        for i in xrange(1000):
            if not verbosity: print '\b\b\b\b%03d' % i,
            sys.stdout.flush()
            if verbosity: print '=== iteration %d' % i
            action = random.choice(['append', 'insert', 'overwrite', 'delete',
                                    'checkpoint'
                                    ]
                                   )
            if action == 'append':
                val = random.random()
                if verbosity: print 'appending %s' % val
                self.items.append(val)
                self.blist.append(val)
            elif action == 'insert':
                val = random.random()
                index = random.randrange(len(self.items) or 1)
                if verbosity: print 'inserting %s at %d' % (val, index)
                self.items.insert(index, val)
                self.blist.insert(index, val)
            elif action == 'overwrite':
                val = random.random()
                index = random.randrange(len(self.items) or 1)
                if verbosity: print 'overwriting %s at %d' % (val, index)
                self.items[index] = val
                self.blist[index] = val
            elif action == 'delete':
                if  self.items:
                    index = random.randrange(len(self.items))
                    if verbosity: print 'deleting at %d' % index
                    del self.items[index]
                    del self.blist[index]
            elif action == 'checkpoint':
                if verbosity: print 'checkpointing'
                self.env.checkpoint()
                del self.env, self.blist
                self.loadDB()
                self.blist.checkIntegrity()
            else:
                assert 0, 'unsupported action %s' % action

            if verbosity > 1: self.blist.dump()
            self.checkContents()

unittest.main()
